<script setup lang="ts">
import { useMonacoEditor } from '@/hooks/web/useMonacoEditor'
import { onMounted, computed, watch, ref } from 'vue'
import { ElSelect, ElOption, ElFormItem, ElForm } from 'element-plus'
import { languageOptions, themeOptions } from './config'
import 'monaco-editor/esm/vs/editor/editor.all.js';

// support all editor features
import 'monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.js';
import 'monaco-editor/esm/vs/editor/standalone/browser/inspectTokens/inspectTokens.js';
import 'monaco-editor/esm/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.js';
import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess.js';
import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.js';
import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess.js';
import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess.js';
import 'monaco-editor/esm/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.js';
import 'monaco-editor/esm/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.js';
import 'monaco-editor/esm/vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.js';

import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';


import { MonacoLanguageClient, CloseAction, ErrorAction, MonacoServices, MessageTransports } from 'monaco-languageclient';
import { BrowserMessageReader, BrowserMessageWriter } from 'vscode-languageserver-protocol/browser';
import { listen, MessageConnection } from "vscode-ws-jsonrpc";


const ReconnectingWebSocket = require("reconnecting-websocket");



const props = withDefaults(
  defineProps<{
    width?: string | number
    height?: string | number
    languageSelector?: boolean
    language?: string
    themeSelector?: boolean
    theme?: string
    editorOption?: Object
    modelValue: string
  }>(),
  {
    width: '100%',
    height: '100%',
    languageSelector: true,
    language: 'python',
    themeSelector: true,
    theme: 'vs',
    editorOption: () => ({}),
    modelValue: ''
  }
)


//////////////////




// function createLanguageClient (transports: MessageTransports): MonacoLanguageClient {
//     return new MonacoLanguageClient({
//         name: 'Sample Language Client',
//         clientOptions: {
//             // use a language id as a document selector
//             documentSelector: [{ language: 'python' }],
//             // disable the default error handler
//             errorHandler: {
//                 error: () => ({ action: ErrorAction.Continue }),
//                 closed: () => ({ action: CloseAction.DoNotRestart })
//             }
//         },
//         // create a language client connection to the server running in the web worker
//         connectionProvider: {
//             get: () => {
//                 return Promise.resolve(transports);
//             }
//         }
//     });
// }




//////////////////

const emits = defineEmits<{
  (e: 'blur'): void
  (e: 'update:modelValue', val: string): void
}>()


const {
  monacoEditorRef,
  createEditor,
  updateVal,
  updateOptions,
  getEditor,
  changeLanguage,
  changeTheme
} = useMonacoEditor(props.language)

onMounted(() => {
  const monacoEditor = createEditor(props.editorOption)
  updateMonacoVal(props.modelValue)
  monacoEditor?.onDidChangeModelContent(() => {
    emits('update:modelValue', monacoEditor!.getValue())
  })
  monacoEditor?.onDidBlurEditorText(() => {
    emits('blur')
  })

  // monaco.languages.register({
  // id: "python",
  // extensions: [".python", ".py", ".pyd"],
  // aliases: ["Python", "python"],
  // mimetypes: ["application/json"],
  // });

  // MonacoServices.install();

  // const worker = new Worker(new URL('./dist/serverWorker-es.js', window.location.href).href);
  // const reader = new BrowserMessageReader(worker);
  // const writer = new BrowserMessageWriter(worker);
  // const languageClient = createLanguageClient({ reader, writer });
  // languageClient.start();

  // reader.onClose(() => languageClient.stop());

})

watch(
  () => props.modelValue,
  () => {
    updateMonacoVal(props.modelValue)
  }
)

const localLanguage = ref(props.language)

watch(localLanguage, (newLanguage) => {
  changeLanguage(newLanguage)
})

const localTheme = ref(props.theme)
watch(localTheme, (newTheme) => {
  changeTheme(newTheme)
})

function updateMonacoVal(val: string) {
  if (val !== getEditor()?.getValue()) {
    updateVal(val)
  }
}

defineExpose({ updateOptions })
</script>

<template>
  <div class="editor-wrapper">
    <div style="height: 50px;">
      <ElForm :inline="true">
        <ElFormItem v-if="languageSelector" label="language" class="w-30% mb-5px!">
          <ElSelect
            v-model="localLanguage"
            placeholder="Please select language"
            size="small"
            filterable
            style="width: 100px;"
          >
            <ElOption
              v-for="item in languageOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </ElSelect>
        </ElFormItem>
        <ElFormItem v-if="themeSelector" label="theme" class="w-30% mb-5px!">
          <ElSelect v-model="localTheme" placeholder="Please select language" size="small" filterable style="width: 100px;">
            <ElOption
              v-for="item in themeOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </ElSelect>
        </ElFormItem>
      </ElForm>
    </div>
    <div style="display: flex;flex-grow: 1;">
      <div ref="monacoEditorRef" class="editor" style="display: block;width: 100%;height: 100%;"></div>
    </div>
  </div>
  
  
</template>

<style scoped>
.editor-wrapper {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
}
</style>
